package com.imaginaryphysics.www.simplepairs;

/**
 * Class representing the matching of two Pairable objects. A Paried object can be associated with a Calculation and a Result to form a unique bonding between the
 * two elements. For more information and examples of see ......
 *
 * @param <T>  Class of paired objects. (Paired Objects must be of the same type)
 */

public class Pair <T extends Pairable> {

	private Relationship relationship;
	
	private T one;
	private T two;
	
	
	/**
	 * Constructs a Pair of Pairable Objects.
	 * 
	 * @param one Object of class type C
	 * @param two Second Object of class type C
	 */
	
	
	public Pair(T one, T two){
	this.one = one;
	this.two = two;
	}
	
	/**
	 * Returns the first of the Paired objects. 
	 * 
	 * @return Paired Object.
	 */
	
	public  T get_obj_one(){
		return one;
	}
	
	/**
	 * Returns the second of the Paired objects. 
	 * 
	 * @return Paired Object.
	 */
	
	public T get_obj_two(){
		return two;
	}
	
	
	/**
	 * Given one of the objects in the pairing returns the other object. If the object passed is not part of the pairing returns null. 
	 * 
	 * @param test An object of the pairing.
	 * @return The other object.
	 */
	public T get_partner(Object test){
		
		if( test == one){
			return two;
		}
		if( test == two){
			return one;
		}
		return null;
	}
	
	
	/**
	 * Test to see if given object is part of the pair.
	 * 
	 * @param test Object to test to see if it is part of Pairing.
	 * @return True if the object passed is part of this Pairing. False if the object is not part of this Pairing.
	 */
	
	public boolean is_part_of_pair(Object test){
		if(test == one){
		return true;
		}		
		if(test ==two){
		return true;
		}
		return false;
	}
	
	
	/**
	 * Attaches an algorithm to run on paired objects. 
	 * 
	 * @param <R> The class of the your Result object. The result object must extend the marker class Result.
	 * @param calculation Your calculation object. The calculation object must be an extension of  the calculation class. The calculation class has access to all public methods and variables of the Paired objects. It also has access to all public  methods and variables of the passed Result object. For how to properly create your calculation class and the logic behind how it functions see \<here\>.
	 * @param result Your result object. For information on how to properly construct a result object please see \<here\>
	 */
	

	
	public  <R extends Result_block> void create_relationship(Calculation<T,R> calculation , R result){
		relationship = new Relationship( this, calculation , result);
	}
	
	/**
	 * Runs the calculation you passed to the create_relationship() function. Runs the run block of your Calculation. If you used this block to pass any results to the result block you can retrieve them by calling the get_result() function.
	 */
	
	public void calculate(){
		 relationship.calculate();
	}
	
	/**
	 * Call to get the Result block of this pairing.
	 * 
	 * @return Returns your Result object. Your result object must be cast to the appropriate type before being used.
	 */
	
	public Result_block get_result(){
		return relationship.get_result();
	}
	
	
}
